package org.dromara.web.service.business;


import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.DeviceType;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mongo.ChatMessage;
import org.dromara.common.mongo.ChatMessageMongoDao;
import org.dromara.common.mongo.SessionMongoDao;
import org.dromara.dao.business.domain.*;
import org.dromara.dao.business.enums.UserTypeEnums;
import org.dromara.dao.business.mapper.*;
import org.dromara.web.controller.app.req.ChatBody;
import org.dromara.web.controller.app.req.TextToImageBody;
import org.dromara.web.plugins.aligreen.AliGreenHelper;
import org.dromara.web.plugins.provider.ModelProviderFactory;
import org.dromara.web.plugins.provider.SsEmitterResponseBody;
import org.dromara.web.plugins.provider.TextToImageModelProviderFactory;
import org.dromara.web.utils.UserTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
@Slf4j
public class ChatService {

    @Autowired
    ChatMessageMongoDao chatMessageMongoDao;
    @Autowired
    SessionMongoDao sessionMongoDao;
    @Autowired
    ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    ModelProviderFactory modelProviderFactory;
    @Autowired
    TextToImageModelProviderFactory textToImageModelProviderFactory;
    @Autowired
    ModelMapper modelMapper;
    @Autowired
    UserService userService;
    @Autowired
    SmartAgentMapper smartAgentMapper;
    @Autowired
    SmartAgentService smartAgentService;
    @Autowired
    SmartAgentSettingService smartAgentSettingService;
    @Autowired
    ModelParamMapper modelParamMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    AliGreenHelper aliGreenHelper;
    @Autowired
    GreenWordMapper greenWordMapper;


    @Transactional
    public void chatMessage(ChatBody chatBody, SseEmitter emitter, LoginUser loginUser, String lang, String ip) {
        boolean newSession = false;
        if (StringUtils.isEmpty(chatBody.getSessionId())) {
            chatBody.setSessionId(UUID.randomUUID().toString().replace("-", ""));
            newSession = true;
        }
        User user = userMapper.selectById(loginUser.getUserId());
        boolean greenRet = aliGreenHelper.checkText(chatBody.getMessage());
        GreenWord greenWord = new GreenWord();
        greenWord.setUserId(user.getId());
        greenWord.setUserName(user.getUsername());
        greenWord.setIpAddress(ip);
        greenWord.setContent(chatBody.getMessage());
        greenWord.setPass(greenRet);
        greenWordMapper.insert(greenWord);
        if (!greenRet) {
            try {
                emitter.send(SsEmitterResponseBody.builder()
                    .status(SsEmitterResponseBody.STATUS_ERROR)
                    .sessionId(chatBody.getSessionId())
                    .msg("您的提问涉及到敏感词汇，请修改后再提交")
                    .build());
                emitter.complete();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }



        Model model = null;
        SmartAgent smartAgent = null;
        if (chatBody.getAgentId() == null) {
            model = modelMapper.selectById(chatBody.getModelId());
        } else {
            smartAgent = smartAgentService.agentDetail(chatBody.getAgentId(), lang);
            model = modelMapper.selectById(smartAgent.getModelId());
            chatBody.setPrompt(smartAgent.getPrompt());
        }
        Model finalModel = model;
        SmartAgent finalAgent = smartAgent;
        try {

            Integer userType = UserTypeUtils.userType(user);
            // 如果用户有套餐  则不扣费用
            if (UserTypeEnums.USER_TYPE_COMMON.equals(userType) || (UserTypeEnums.USER_TYPE_MOBILE.equals(userType) && DeviceType.PC.getDevice().equals(loginUser.getDeviceType()))) {
                userService.userBalanceChange(loginUser.getUserId(), -model.getDiamondFee(), -model.getStarFee(), "模型调用费用");
            }

            if (chatBody.getAgentId() != null) {
                threadPoolTaskExecutor.execute(() -> {
                    smartAgentSettingService.updateAgentLastChatTime(loginUser.getUserId(), chatBody.getAgentId());
                });
            }

            if (chatBody.getRefresh() == null || !chatBody.getRefresh()) {
                ChatMessage chatMessage = new ChatMessage();
                chatMessage.setUserId(loginUser.getUserId());
                chatMessage.setSessionId(chatBody.getSessionId());
                chatMessage.setImage(chatBody.getImage());
                chatMessage.setMessageId(UUID.randomUUID().toString().replace("-", ""));
                chatMessage.setRole("user");
                chatMessage.setAsk(true);
                chatMessage.setType(ChatMessage.TYPE_TXT);
                chatMessage.setFileId(chatBody.getFileId());
                chatMessage.setFileName(chatBody.getFileName());
                chatMessage.setFileSize(chatBody.getFileSize());
                chatMessage.setContent(chatBody.getMessage());
                chatMessage.setTime(LocalDateTime.now());
                chatMessageMongoDao.saveOrUpdate(loginUser.getUserId(), chatMessage);
                if (newSession) {

                    sessionMongoDao.saveOrUpdate(loginUser.getUserId(), chatMessage.getContent(), chatMessage.getSessionId(), chatBody.getAgentId(),
                        smartAgent == null ? null : smartAgent.getName(),
                        smartAgent == null ? model.getName() : smartAgent.getName()
                    );
                }
            }

            modelProviderFactory.chat(chatBody, model, emitter, (responseMessage, role) -> {

                ChatMessage responseChatMessage = new ChatMessage();
                responseChatMessage.setUserId(loginUser.getUserId());
                responseChatMessage.setSessionId(chatBody.getSessionId());
                responseChatMessage.setMessageId(UUID.randomUUID().toString().replace("-", ""));
                responseChatMessage.setAsk(false);
                responseChatMessage.setRole(role);
                responseChatMessage.setContent(responseMessage);
                if (finalAgent == null) {
                    responseChatMessage.setModelName(finalModel.getName());
                    responseChatMessage.setModelIcon(finalModel.getIcon());
                } else {
                    responseChatMessage.setModelName(finalAgent.getName());
                    responseChatMessage.setModelIcon(finalAgent.getIcon());
                }
                responseChatMessage.setTime(LocalDateTime.now());
                responseChatMessage.setType(ChatMessage.TYPE_TXT);
                chatMessageMongoDao.saveOrUpdate(loginUser.getUserId(), responseChatMessage);
            }, false);

        } catch (Exception e) {
            try {
                emitter.send(SsEmitterResponseBody.builder()
                    .status(SsEmitterResponseBody.STATUS_ERROR)
                    .sessionId(chatBody.getSessionId())
                    .appLocale(lang)
                    .msg(e.getMessage())
                    .build());
                emitter.complete();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
//            try {
//                emitter.send(SsEmitterResponseBody.builder()
//                    .status(SsEmitterResponseBody.STATUS_ERROR)
//                    .sessionId(chatBody.getSessionId())
//                    .msg(e.getMessage())
//                    .build());
//                emitter.complete();
//            } catch (Exception e1) {
//            }
//            throw e;
        }

    }


    public void chatMessage(ChatBody chatBody, SseEmitter emitter) {
        Long modelId = 1881262807234514946L;
        Model model = modelMapper.selectById(modelId);
        modelProviderFactory.chat(chatBody, model, emitter, (responseMessage, role) -> {

        }, true);
    }


    @Transactional
    public SsEmitterResponseBody ImageChatMessage(TextToImageBody chatBody, LoginUser loginUser) {
        boolean newSession = false;
        if (StringUtils.isEmpty(chatBody.getSessionId())) {
            chatBody.setSessionId(UUID.randomUUID().toString().replace("-", ""));
            newSession = true;
        }
        Model model = modelMapper.selectById(chatBody.getModelId());

        try {
            userService.userBalanceChange(loginUser.getUserId(), -model.getDiamondFee(), -model.getStarFee(), "模型调用费用");
        } catch (Exception e) {

        }


        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setUserId(loginUser.getUserId());
        chatMessage.setSessionId(chatBody.getSessionId());
        chatMessage.setMessageId(UUID.randomUUID().toString().replace("-", ""));
        chatMessage.setRole("user");
        chatMessage.setAsk(true);
        chatMessage.setType(ChatMessage.TYPE_TXT);
        chatMessage.setContent(chatBody.getPrompt());
        chatMessage.setTime(LocalDateTime.now());
        chatMessageMongoDao.saveOrUpdate(loginUser.getUserId(), chatMessage);
        if (newSession) {
            SmartAgent smartAgent = null;

            sessionMongoDao.saveOrUpdate(loginUser.getUserId(), chatMessage.getContent(), chatMessage.getSessionId(), null, null, model.getName());
        }
        ModelParam modelParam = null;
        if (chatBody.getModelParamId() != null) {
            modelParam = modelParamMapper.selectById(chatBody.getModelParamId());
        }

        String image = textToImageModelProviderFactory.textToImage(model, chatBody.getPrompt(), modelParam, chatBody.getScale());

        ChatMessage responseChatMessage = new ChatMessage();
        responseChatMessage.setUserId(loginUser.getUserId());
        responseChatMessage.setSessionId(chatBody.getSessionId());
        responseChatMessage.setMessageId(UUID.randomUUID().toString().replace("-", ""));
        responseChatMessage.setAsk(false);
        responseChatMessage.setImage(image);
        responseChatMessage.setModelName(model.getName());
        responseChatMessage.setModelIcon(model.getIcon());
        responseChatMessage.setTime(LocalDateTime.now());
        responseChatMessage.setType(ChatMessage.TYPE_IMAGE);
        chatMessageMongoDao.saveOrUpdate(loginUser.getUserId(), responseChatMessage);

        SsEmitterResponseBody body = SsEmitterResponseBody.builder()
            .image(image)
            .sessionId(chatBody.getSessionId())
            .status(SsEmitterResponseBody.STATUS_OK)
            .build();

        return body;
    }


    public String ImageChatMessage(TextToImageBody chatBody) {
        Model model = modelMapper.selectById(chatBody.getModelId());
        ModelParam modelParam = null;
        if (chatBody.getModelParamId() != null) {
            modelParam = modelParamMapper.selectById(chatBody.getModelParamId());
        }
        String image = textToImageModelProviderFactory.textToImage(model, chatBody.getPrompt(), modelParam, chatBody.getScale());
        return image;
    }
}
